using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using System.IO.IsolatedStorage;
using System.IO;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using GameStateManagement;
using Microsoft.Phone.Shell;
using System.Xml.Serialization;
using System.Net.Sockets;
using System.Net;

namespace PiratesOfBermuda
{
    public class MultiPlayerGameProcessor : GameProcessor
    {        
        public UdpAnySourceMulticastChannel Channel;
        public string playerIdentifier;
        public string opponentIndentifier;
        public bool isEnemyShipMoveSoundPlayed = false;        

        // Game Objects
        public Player opponentPlayer;

        public MultiPlayerGameProcessor(Game game, SpriteBatch spriteBatch)
            : base(game, spriteBatch)
        {
            //Init socket
            InitializeSockets();
            //Khoi tao ngau nhien 1 con so lam identifier cua  Host
            Random random = new Random();
            playerIdentifier = random.Next(int.MaxValue).ToString();
            Channel.Identifier = playerIdentifier;
        }

        protected void InitializeSockets()
        {
            this.Channel = new UdpAnySourceMulticastChannel(IPAddress.Parse("224.109.108.107"), 3008);
            this.Channel.PacketReceived += new EventHandler<UdpPacketReceivedEventArgs>(Channel_PacketReceived);
            this.Channel.Open();
        }

        #region PROCESS PACKETS
        protected virtual void handleMessagesFromOpponent(string[] mess) { }

        protected virtual void checkConnectedState(UdpPacketReceivedEventArgs e) {}

        protected void handleFireEventFromOpponent(string[] mess)
        {
            Point? p1, p2;
            bool is1Exploded = false, is2Exploded = false;

            if (mess[2] == "null")
                p1 = null;
            else
            {
                p1 = new Point(int.Parse(mess[2]), int.Parse(mess[3]));
                if (mess[4] == "True")
                    is1Exploded = true;
            }

            if (mess[5] == "null")
                p2 = null;
            else
            {
                p2 = new Point(int.Parse(mess[5]), int.Parse(mess[6]));
                if (mess[7] == "True")
                    is2Exploded = true;
            }

            opponentPlayer.Fire(p1, is1Exploded, p2, is2Exploded);
            AudioManager.PlaySound("Boom");
        }

        protected void Channel_PacketReceived(object sender, UdpPacketReceivedEventArgs e)
        {
            string[] mess = e.Message.Split(',');

            checkConnectedState(e);

            //Chi nhan message tu opponent da ket noi
            if (mess[0] == opponentIndentifier)
            {
                handleMessagesFromOpponent(mess);
            }
        }
        #endregion

        #region PACKETS PROCESS METHODS

        public void ObjectsCustomMove(string[] messages)
        {
            switch (messages[2])
            {
                case "Client":
                case "Host":
                    List<Point> positions = new List<Point>();
                    positions.Add(new Point(Int32.Parse(messages[3]), Int32.Parse(messages[4])));
                    if (messages[1] == "MoveAndWhirl")
                        positions.Add(new Point(Int32.Parse(messages[5]), Int32.Parse(messages[6])));
                    ProcessOpponentMove(positions);
                    break;
                case "Enemy":
                    BasicEnemy enemy = (BasicEnemy)gameObjects[(messages[3] + "_" + messages[4])];
                    enemy.Move(Int32.Parse(messages[5]), Int32.Parse(messages[6]));
                    if (!isEnemyShipMoveSoundPlayed)
                    {
                        AudioManager.PlaySound("MoveEvil");
                        isEnemyShipMoveSoundPlayed = true;
                    }
                    break;
            }
        }

        protected void sendMessages()
        {
            for (int i = 0; i < messages.Count; i++)
                Channel.Send(messages[i]);
        }
        #endregion

        /// <summary>
        /// Khoi tao doi tuong tau cua doi phuong
        /// </summary>
        //public void GenerateOpponentPlayer(int x, int y, string name)
        //{
        //    opponentPlayer = new Player(game, spriteBatch);
        //    opponentPlayer.InitializeClient();
        //    opponentPlayer.Name = name;
        //    opponentPlayer.X = x;
        //    opponentPlayer.Y = y;
        //    gameObjects.Add(x.ToString() + "_" + y.ToString(), opponentPlayer);
        //    opponentPlayer.IsActive = true;
        //}

        #region Game Objects Processing
        public void ProcessOpponentMove(List<Point> points)
        {
            gameObjects.Remove(opponentPlayer.X.ToString() + "_" + opponentPlayer.Y.ToString());
            switch (points.Count)
            {
                case 1: // Simple Move
                    opponentPlayer.Move(points[0].X, points[0].Y);
                    gameObjects.Add(points[0].X + "_" + points[0].Y, opponentPlayer);
                    break;
                case 2: // Move and Whirl
                    opponentPlayer.MoveAndWhirl(points[0], points[1]);
                    gameObjects.Add(points[1].X + "_" + points[1].Y, opponentPlayer);
                    break;
            }
            AudioManager.PlaySound("MoveGood");
        }        
        #endregion

        #region UPDATE
        public virtual void CheckGameObjectsState() {}        

        protected override void removeSpecifiedShip(string key)
        {
            if (gameObjects[key].GetType() == typeof(BasicEnemy))
            {
                base.removeSpecifiedShip(key);
            }
            else if (gameObjects[key].GetType() == typeof(Player))
            {
                gameObjects[key].Destroyed = true;
            }
        }

        public virtual void UpdateOpponentPlayer(GameTime gameTime)
        {            
            UpdateCustomPlayer(ref opponentPlayer, gameTime);
        }
        #endregion

        #region DRAW        

        protected override void DrawPlayer(GameTime gameTime)
        {
            base.DrawPlayer(gameTime);
            opponentPlayer.Draw(gameTime);
        }
        #endregion        
    }
}